import {_decorator, CCFloat, Component, find, Node, Prefab, Vec3} from 'cc';
import {EventManager} from "db://assets/Scripts/Common/EventManager";
import {EventType} from "db://assets/Scripts/Common/EventType";
import {BulletType} from "db://assets/Scripts/MVC/Bullet/BulletType";
import {SPolicy} from "db://assets/Scripts/MVC/Bullet/SPolicy";
import {HPolicy} from "db://assets/Scripts/MVC/Bullet/HPolicy";
import {MPolicy} from "db://assets/Scripts/MVC/Bullet/MPolicy";
import {NodePath} from "db://assets/Scripts/Common/NodePath";
import {AudioManager} from "db://assets/Scripts/Common/AudioManager";
import {AudioPath} from "db://assets/Scripts/Common/AudioPath";

const {ccclass, property} = _decorator;

/**
 * 子弹管理
 */
@ccclass('BulletManager')
export class BulletManager extends Component {
    /**
     * 玩家
     * 发射子弹需要知道玩家的位置
     */
    private playerNode: Node = null;
    /**
     * 子弹01
     */
    @property(Prefab)
    public bullet01Prefab: Prefab = null;
    /**
     * 子弹02
     */
    @property(Prefab)
    public bullet02Prefab: Prefab = null;
    /**
     * 子弹03
     */
    @property(Prefab)
    public bullet03Prefab: Prefab = null;
    /**
     * 子弹04
     */
    @property(Prefab)
    public bullet04Prefab: Prefab = null;
    /**
     * 子弹05
     */
    @property(Prefab)
    public bullet05Prefab: Prefab = null;
    /**
     * 攻击间隔
     */
    @property(CCFloat)
    public attackInterval: number = 0.5;

    /**
     * 当前子弹预制体
     * 子弹预制体可以切换
     */
    private bulletPrefab: Prefab = null;
    /**
     * 移动速度
     */
    private speed: Vec3 = new Vec3(20, 20, 20);
    /**
     * 攻击间隔
     */
    private currentAttackInterval: number = 0;
    /**
     * 是否攻击
     */
    private attacking: boolean = false;
    /**
     * 子弹类型
     */
    private bulletType: BulletType = BulletType.M;
    /**
     * 子弹S、H、M
     */
    private bulletS: SPolicy = null;
    private bulletH: SPolicy = null;
    private bulletM: SPolicy = null;

    onLoad() {
        // 设置子弹初始预制体
        this.bulletPrefab = this.bullet01Prefab;
        // 此设置保证第一颗子弹发射，如果是0的话，则需要等一段时间的累计
        this.currentAttackInterval = this.attackInterval;

        // 初始化子弹策略
        this.bulletS = new SPolicy();
        this.bulletH = new HPolicy();
        this.bulletM = new MPolicy();
    }

    onEnable() {
        // 订阅事件
        EventManager.on(EventType.RESTART, this.onRestart, this);
        EventManager.on(EventType.ATTACKING, this.onIsAttacking, this);
        EventManager.on(EventType.UPDATE_BULLET, this.onChangeBullet, this);
    }

    onDisable() {
        // 取消订阅事件
        EventManager.off(EventType.RESTART, this.onRestart, this);
        EventManager.off(EventType.ATTACKING, this.onIsAttacking, this);
        EventManager.off(EventType.UPDATE_BULLET, this.onChangeBullet, this);
    }

    start() {

    }

    update(deltaTime: number) {
        // 累加发射周期
        this.currentAttackInterval += deltaTime;
        // 当玩家存活，并且当前是可以发射子弹的，还达到发射周期时
        if (this.playerNode
            && this.playerNode.active
            && this.attacking
            && this.currentAttackInterval >= this.attackInterval) {
            // 创建子弹
            this.createPlayerBullet();
            // 播放发射子弹音效
            this.playBulletSound();
            // 重置发射周期
            this.currentAttackInterval = 0;
        }
    }

    /**
     * 当创建玩家时
     */
    private onRestart() {
        // 销毁所有子节点
        this.node.destroyAllChildren();

        // 初始化玩家节点
        this.playerNode = find(NodePath.PLAYER);
        // 重置子弹类型、预制体、速度、攻击间隔
        this.bulletType = BulletType.M;
        this.bulletPrefab = this.bullet05Prefab;
        this.speed = new Vec3(20, 20, 20);
    }

    /**
     * 创建玩家飞机子弹
     */
    private createPlayerBullet() {
        switch (this.bulletType) {
            case BulletType.S:
                this.bulletS.combination(this.bulletPrefab, this.node, this.playerNode, this.speed);
                break;
            case BulletType.H:
                this.bulletH.combination(this.bulletPrefab, this.node, this.playerNode, this.speed);
                break;
            case BulletType.M:
                this.bulletM.combination(this.bulletPrefab, this.node, this.playerNode, this.speed);
                break;
        }
    }

    /**
     * 播放发射子弹音效
     */
    private playBulletSound() {
        let audioPath: string = null;
        switch (this.bulletType) {
            case BulletType.S:
                audioPath = AudioPath.bullet1Sound;
                break;
            case BulletType.H:
                audioPath = AudioPath.bullet1Sound;
                break;
            case BulletType.M:
                audioPath = AudioPath.bullet2Sound;
                break;
        }
        // 当子弹音效路径存在时
        if (audioPath) {
            // 播放发射子弹音效
            AudioManager.getInstance().playSound(audioPath);
        }
    }

    /**
     * 是否攻击
     *
     * @param attacking true 攻击；false 不攻击。
     */
    private onIsAttacking(attacking: boolean) {
        this.attacking = attacking;
    }

    /**
     * 改变子弹类型
     *
     * @param bulletType 子弹类型
     */
    private onChangeBullet(bulletType: BulletType) {
        // 吃到相同的子弹类型，攻击速度+1
        if (this.bulletType === bulletType) {
            this.speed = new Vec3(this.speed.x + 10, this.speed.y + 10, this.speed.z + 10);
        } else {
            this.speed = new Vec3(20, 20, 20);
        }

        // 记录子弹类型
        this.bulletType = bulletType;

        // 切换子弹模型
        switch (bulletType) {
            case BulletType.S:
                this.bulletPrefab = this.bullet01Prefab;
                break;
            case BulletType.H:
                this.bulletPrefab = this.bullet03Prefab;
                break;
            case BulletType.M:
                this.bulletPrefab = this.bullet05Prefab;
                break;
        }
    }
}